<?php
require_once ABSPATH . 'Upay/Upay/common.php';
require_once ABSPATH . 'Upay/Upay/mer2Plat.php';
require_once ABSPATH . 'Upay/Upay/mer2PlatUtil.php';
require_once ABSPATH . 'Upay/Upay/plat2Mer.php';

define('REFUND_SUCCESS', 'REFUND_SUCCESS');
define('REFUND_FAIL', 'REFUND_FAIL');

/**
 *  首次支付. 将会直接跳到联动那边支付.
 *  http://weixin.test/Upay/submitUpay.json?order_id=12312321312&amount=1&pay_type=CREDITCARD&gate_id=CMB; 
 *  
 *  签约支付. 根据支付类型跟支付银行拿到协议支付ID. 发送请求到联动, 向支付银行预留的手机发送验证码. 
 *  http://weixin.test/Upay/submitUpay.json?order_id=12312321312&amount=1&pay_type=CREDITCARD&gate_id=CMB; 
 *  
 *  拿到验证码, trade_no, 协议支付ID 进行支付
 *  http://weixin.test/Upay/protocolPay.json?smsCode=8768&trade_no=1407180043454125&usr_pay_agreement_id=P2014071612321300000000001447388
 */

class UpayAction extends Action{
	
	public $merId; 		//商户编号
	public $merCustId; 	//用户在商户端的唯一标识
	public $signType;	//签名类型
	public $sign;		//签名
	public $charset;	//字符集
	public $version;	//版本号
	public $merPrive;	//私有域
	
	public function __construct(){
		/*
		session_start();
		$_GET['session_id'] = session_id();
		$retVal = Session::init();
		if (!$retVal) {
			Output::instance()->resultCode(code_access_denied);
			return;
		}*/
		
		$this->merId = 9086;
		$this->merCustId = Session::$user['userName'];
		$this->signType = 'RSA';
		$this->sign = urlencode(SignUtil::sign2("merId"."=".$this->merId."&"."merCustId"."=".$this->merCustId,$this->merId));
		$this->charset = 'UTF-8';
		$this->version = '4.0';
		
		$this->merPrive = Session::$user['customerId'];
	}

	/**
	 * 向联动优势下单
	 */
	private function placeOrder($sn, $amount, $desc, $ret_url){
		$amount = $amount*100;
		$service = "pay_req_shortcut";
		$charset = $this->charset;
		$mer_id = $this->merId;
		$sign_type = $this->signType;
		$res_format = 'HTML';
		
// 		Log::write('ret_url:' . $ret_url);
		$host = C("SERVER_HOST");
		$notify_url = $host."/Upay/notifypay.json";
		
		$version = $this->version;
		$mer_date = date('Ymd');
		$expire_time = ORDER_TIMEOUT;
		$amt_type = 'RMB';
		$user_ip = get_client_ip();
		
		$map = new HashMap ();
		$map->put("service", $service);
		$map->put("charset", $charset);
		$map->put("mer_id", $mer_id);
		$map->put("sign_type", $sign_type);
		$map->put("res_format", $res_format);
		// TODO:屏蔽该地址，回调地址不能超过128位，且不能带有特殊字符后续处理
// 		$map->put("ret_url", $ret_url);
		$map->put("notify_url", $notify_url);
		$map->put("version", $version);
		$map->put("order_id", $sn);
		$map->put("mer_date", $mer_date);
		if (!empty($desc)) {
			$map->put("goods_inf", $desc);
		}
		
		$map->put("amount", $amount);
		$map->put("amt_type", $amt_type);
		$map->put("expire_time", $expire_time);
		$map->put("user_ip", $user_ip);
		
		$map->put("mer_priv", $this->merPrive);
		
		$reqData = MerToPlat::makeRequestDataByGet ($map);
		$url = $reqData->getUrl();
		
		$ch = curl_init($url) ;
		Log::write($url);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true) ; // 获取数据返回
		curl_setopt($ch, CURLOPT_BINARYTRANSFER, true) ; // 在启用 CURLOPT_RETURNTRANSFER 时候将获取数据返回
		$access = curl_exec($ch) ;
		Log::write($access);
		curl_close($ch);
		preg_match('/CONTENT="(.*?)"/s',$access,$res);
		$tmp = explode("&",$res[1]);
		;
		$return = array();
		foreach($tmp as $key=>$value){
			$temp = explode("=",$value);
			if($temp[0] != 'sign'){
				$return[$temp[0]] = $temp[1];
			}else{
				$return[$temp[0]] = $temp[1]."=";
			}
		}
		if($return['ret_code'] == '0000'){
			$array = array();
			$array['trade_no'] = $return['trade_no'];
			$array['trade_state'] = $return['trade_state'];
			
			return $array;
		}else{
			
			return false;
		}
	}
	
	/**
	 * 商户接收支付结果通知验签及响应平台
	 * 
	 */
	public function notifypay() {
		Log::write('in notifypay upay');
		
		$sn = $_GET['order_id'];
		if (!isset($sn)) {
			Log::write('not set order_id');
			return;
		}
		
		// TODO: 签名检查
		$data = new HashMap();
		$data->put("service", $_REQUEST['service']);
		$data->put("charset", $_REQUEST['charset']);
		$data->put("mer_id", $_REQUEST['mer_id']);
		$data->put("sign_type", $_REQUEST['sign_type']);
		$data->put("order_id", $_REQUEST['order_id']);
		$data->put("mer_date", $_REQUEST['mer_date']);
		$data->put("trade_no", $_REQUEST['trade_no']);
		if($_REQUEST['goods_id']!=null) $data->put("goods_id", $_REQUEST['goods_id']);
		$data->put("pay_date", $_REQUEST['pay_date']);
		$data->put("amount", $_REQUEST['amount']);
		$data->put("amt_type", $_REQUEST['amt_type']);
		$data->put("pay_type", $_REQUEST['pay_type']);
		if($_REQUEST['media_id']!=null)
			$data->put("media_id", $_REQUEST['media_id']);
		if($_REQUEST['media_type']!=null)
			$data->put("media_type", $_REQUEST['media_type']);
		$data->put("settle_date", $_REQUEST['settle_date']);
		if($_REQUEST['mer_priv']!=null)
			$data->put("mer_priv", $_REQUEST['mer_priv']);
		$data->put("trade_state", $_REQUEST['trade_state']);
		$data->put("pay_seq", $_REQUEST['pay_seq']);
		if($_REQUEST['error_code']!=null)
			$data->put("error_code", $_REQUEST['error_code']);
		if($_REQUEST['gate_id']!=null)
			$data->put("gate_id", $_REQUEST['gate_id']);
		if($_REQUEST['identity_type']!=null)
			$data->put("identity_type", $_REQUEST['identity_type']);
		if($_REQUEST['identity_code']!=null)
			$data->put("identity_code", $_REQUEST['identity_code']);
		if($_REQUEST['card_holder']!=null)
			$data->put("card_holder", $_REQUEST['card_holder']);
		if($_REQUEST['last_four_cardid']!=null)
			$data->put("last_four_cardid", $_REQUEST['last_four_cardid']);
		if($_REQUEST['usr_busi_agreement_id']!=null)
			$data->put("usr_busi_agreement_id", $_REQUEST['usr_busi_agreement_id']);
		if($_REQUEST['usr_pay_agreement_id']!=null)
			$data->put("usr_pay_agreement_id", $_REQUEST['usr_pay_agreement_id']);
		$data->put("version", $_REQUEST['version']);
		$data->put("sign", $_REQUEST['sign']);
		
		//获取请求数据
		$service = $data->get("service");
		$charset = $data->get("charset");
		$mer_id = $data->get("mer_id");
		$sign_type = $data->get("sign_type");
		$order_id = $data->get("order_id");
		$mer_date = $data->get("mer_date");
		$trade_no = $data->get("trade_no");
		$goods_id = $data->get("goods_id");
		$pay_date = $data->get("pay_date");
		$amount = $data->get("amount");
		$amt_type = $data->get("amt_type");
		$pay_type = $data->get("pay_type");
		$media_id = $data->get("media_id");
		$media_type = $data->get("media_type");
		$settle_date = $data->get("settle_date");
		$mer_priv = $data->get("mer_priv");
		$trade_state = $data->get("trade_state");
		$pay_seq = $data->get("pay_seq");
		$error_code = $data->get("error_code");
		$gate_id = $data->get("gate_id");
		$identity_type = $data->get("identity_type");
		$identity_code = $data->get("identity_code");
		$card_holder = $data->get("card_holder");
		$last_four_cardid = $data->get("last_four_cardid");
		$usr_busi_agreement_id = $data->get("usr_busi_agreement_id");
		$usr_pay_agreement_id = $data->get("usr_pay_agreement_id");
		$version = $data->get("version");
		$sign = $data->get("sign");
		
		
		//获取UMPAY平台请求商户的支付结果通知数据,并对请求数据进行验签,此时商户接收到的支付结果通知会存放在这里,商户可以根据此处的trade_state订单状态来更新订单
		$resData = new HashMap();
		try{
			//获取UMPAY平台请求商户的支付结果通知数据,并对请求数据进行验签
			//如验证平台签名正确，即应响应UMPAY平台返回码为0000。【响应返回码代表通知是否成功，和通知的交易结果（支付失败、支付成功）无关】
			//验签支付结果通知 如验签成功，则返回ret_code=0000
			$reqData = PlatToMer::getNotifyRequestData($data);
		
			$resData->put("ret_code","0000");
		} catch (Exception $e){
			//如果验签失败，则抛出异常，返回ret_code=1111
			System.out.printf("验证签名发生异常" + $e);
		
			$resData->put("ret_code","1111");
		}
		//验签后的数据都组织在resData中。
		//生成平台响应UMPAY平台数据,将该串放入META标签，以下几个参数为结果通知必备参数
		
		
		//生成平台响应UMPAY平台数据,将该串放入META标签
		
		$resData->put("mer_id", $data->get("mer_id"));
		$resData->put("sign_type", $data->get("sign_type"));
		$resData->put("mer_date", $data->get("mer_date"));
		$resData->put("order_id", $data->get("order_id"));
		$resData->put("version", $data->get("version"));
		$resData->put("ret_msg", "success");
		$data = MerToPlat::notifyResponseData($resData);
		
// 		$returnSign = $_GET['sign'];
		if($resData->get('ret_code') == '0000'){
			
			$customerId = $_GET['mer_priv'];
			$transactionId = $_GET['trade_no'];
			
			Session::switchCustomer($customerId);
			$OrderModel = M("module_product_order");
			$whereSn["serialNumber"] = $sn;
			$oid = $OrderModel->where($whereSn)->getField("id");
			if (!$oid) {
				Log::write('upay not found order:' . $OrderModel->getLastSql());
				return;
			}
			$result = ProductOrder::updateOrderDone($customerId, $oid, $transactionId, true);
			if ($result) {
				$returnStr = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"
					. "<HTML><TITLE></TITLE><HEAD></HEAD>" 
					. "<META NAME=\"MobilePayPlatform\"  CONTENT=\"{$data}\" />"
					. "<BODY></BODY></HTML>";
				echo $returnStr;
			} else {
					
			}
		}
	}
	
	/**
	 * 一键支付
	 * $sn 订单编号：由于联动支付要求订单id不能重复，多客户往一个帐号中支付订单id可能重复，所以使用订单编号
	 * 返回值: $return['error'] 失败. 
	 * 			order_error 下单失败, 
	 * 			cannot_find_card_info 找不到卡片信息. 
	 */
	public function submitUpay($sn, $amount, $desc = '', $retUrl = '', $pay_type='CREDITCARD', $gate_id='CMB') {
		
		$return = array();
		//下单
		$order = $this->placeOrder($sn, $amount, $desc, $retUrl);
		
		$trade_no = (!$order) ? "" :  $order['trade_no']; //下单成功后返回的trade_no;
		
		if($trade_no == ''){
// 			OutPut::instance()->objArray(array('order_id'=>$order_id, 'amount'=>$amount, 'desc' => $desc, 'retUrl'=> $retUrl));
			Output::instance()->resultCode(code_product_order_upay_error);
			return;
		}
		//每次都调用首次支付
		$url = $this->firstPay($trade_no);
		$return['success'] = "first_pay";
		$return['url'] = $url;
		Output::instance()->object($return);
		
		/*
		//如果用户 信用卡跟储值卡都未签约则跳到使用首次支付
		if(!$this->searchUserBindCard() && !$this->searchUserBindCard('DEBITCARD')){
			$url = $this->firstPay($trade_no);
			$return['success'] = "first_pay";
			$return['url'] = $url;
			Output::instance()->object($return);
			
		}else{ //如果用户已经有银行卡签约成功则直接跳转协议支付
			
			$card_list_string = $this->searchUserBindCard($pay_type);
			$usr_pay_agreement_id = $this->getProtocolCard($card_list_string, $gate_id);
			if($usr_pay_agreement_id == ''){
				$return['error'] = "cannot_find_card_info"; return $return;
			}
			
			//向签约用户所绑定银行的预留手机发送短信验证码, 验证码获取成功后收集 3个参数 验证码, trade_no, 用户支付协议id. 然后调用 protocolPay 方法进行支付.
			$sendSmsStatus = $this->sendSmsCode($trade_no, $usr_pay_agreement_id);
			$return['success']="protocol_pay";
			$return['param'] = array();
			$return['param']['trade_no'] = $trade_no;
			$return['param']['usr_pay_agreement_id'] = $usr_pay_agreement_id;
			$return['param']['sendSmsStatus'] = $sendSmsStatus;
			Output::instance()->object($return);
		}
		*/
	}
	
	/**
	 * 根据指定支付银行获取签约卡片的用户支付协议号.
	 * 
	 * 参数: $card_list_string 用户绑定银行卡列表字符串, $gate_id 支付银行
	 * 
	 * 返回: 用户支付协议号
	 */
	public function getProtocolCard($card_list_string, $gate_id){
		$usr_pay_agreement_id = '';
		//只签约一张银行卡
		if(strstr($card_list_string,"|") ==NULL){
			$str = explode(",", $card_list_string);
			// 根据指定的银行获取用户支付协议号
			if($str[0] == $gate_id){
				$usr_pay_agreement_id = $str[1];
			}
			
		}else{ // 用户已经签约多张银行卡
			$cardlist = explode("|", $card_list_string);
			foreach($cardlist as $key => $value){
				$tmpstr = explode(",",$value);
				// 根据指定的银行获取用户支付协议号
				if($tmpstr[0] == $gate_id){
					$usr_pay_agreement_id = $tmpstr[1];
				}
			}
		}
		
		return $usr_pay_agreement_id;
	}
	
	/**
	 * 首次支付
	 * 
	 * $orderid 订单号 
	 * $amount	订单金额
	 * $pay_type	支付方式   信用卡.CREDITCARD, 储值卡.DEBITCARD
	 * $gate_id		银行ID CMB//招商银行
	 * 
	 * weixin.test/Upay/firstPay.json?order_id=3232323232&amount=1 //跳到招行的信用卡支付
	 */
	public function firstPay($trade_no){
// 		$url = "https://m.soopay.net/q/html5/index.do?tradeNo=".$tradeNo;
		$url = <<<URL
https://m.soopay.net/q/html5/index.do?tradeNo={$trade_no}&merCustId={$this->merCustId}
URL;
		return $url;
	}
	
	
	/**
	 * 下发手机短信验证码
	 * 
	 * $trade_no 下单成功后返回的联动优势的交易号, $usr_pay_agreement_id 用户支付标识.
	 * 
	 * 返回值: true: 发送成功, false: 发送失败
	 */
	public function sendSmsCode($trade_no, $usr_pay_agreement_id){
		
		//获取短信验证码
		$service = "req_smsverify_shortcut";
		$charset = $this->charset;
		$mer_id = $this->merId;
		$sign_type = $this->signType;
		$res_format = "HTML";
		$version = $this->version;
		$mer_cust_id = $this->merCustId;
		
		$map = new HashMap();
		$map->put("service", $service);
		$map->put("charset", $charset);
		$map->put("mer_id", $mer_id);
		$map->put("sign_type", $sign_type);
		$map->put("res_format", $res_format);
		$map->put("version", $version);
		$map->put("trade_no", $trade_no);
		$map->put("mer_cust_id", $mer_cust_id);
		$map->put("usr_pay_agreement_id", $usr_pay_agreement_id);
		
		$reqData = MerToPlat::makeRequestDataByGet($map);
		$url = $reqData->getUrl();
		
		$ch = curl_init($url) ;
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true) ; // 获取数据返回
		curl_setopt($ch, CURLOPT_BINARYTRANSFER, true) ; // 在启用 CURLOPT_RETURNTRANSFER 时候将获取数据返回
		$access = curl_exec($ch) ;
		curl_close($ch);
		
		preg_match('/CONTENT="(.*?)"/s',$access,$res);
		$tmp = explode("&",$res[1]);
			
		$return = array();
		foreach($tmp as $key=>$value){
			$temp = explode("=",$value);
			if($temp[0] != 'sign'){
				$return[$temp[0]] = $temp[1];
			}else{
				$return[$temp[0]] = $temp[1]."=";
			}
		}
		return ($return['ret_code'] == '0000') ? true : false;
	}
	
	/**
	 * 获取到手机验证码后 签约付款确认支付.
	 * 
	 * 返回值: Array
	 *			'amount'		支付金额
	 *			'amt_type'		支付类型
	 *			'mer_date'		订单日期
	 *			'mer_id'		商户标识
	 *			'order_id'		订单号
	 *			'pay_date'		支付日期
	 *			'ret_code'		返回码
	 *			'ret_msg'		返回信息
	 *			'settle_date'	对账日期
	 *			'sign_type'		签名类型
	 *			'trade_state'	交易状态
	 *			'version'		版本号
	 *			'sign'			签名
	 */
	public function protocolPay($smsCode, $trade_no, $usr_pay_agreement_id){
		$service = "agreement_pay_confirm_shortcut";
		$charset = $this->charset;
		$mer_id = $this->merId;
		$sign_type = $this->signType;
		$res_format = "HTML";
		$version = $this->version;
		$verify_code = $smsCode;
		$mer_cust_id = $this->merCustId;
		
		$map = new HashMap();
		$map->put("service", $service);
		$map->put("charset", $charset);
		$map->put("mer_id", $mer_id);
		$map->put("sign_type", $sign_type);
		$map->put("res_format", $res_format);
		$map->put("version", $version);
		$map->put("trade_no", $trade_no);
		$map->put("verify_code", $verify_code);
		$map->put("mer_cust_id", $mer_cust_id);
		$map->put("usr_pay_agreement_id", $usr_pay_agreement_id);
		
		
		$reqData = MerToPlat::makeRequestDataByGet($map);
		$url = $reqData->getUrl();
		
		$ch = curl_init($url) ;
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true) ; // 获取数据返回
		curl_setopt($ch, CURLOPT_BINARYTRANSFER, true) ; // 在启用 CURLOPT_RETURNTRANSFER 时候将获取数据返回
		$access = curl_exec($ch) ;
		curl_close($ch);
		

		preg_match('/CONTENT="(.*?)"/s',$access,$res);
		$tmp = explode("&",$res[1]);
			
		$return = array();
		foreach($tmp as $key=>$value){
			$temp = explode("=",$value);
			if($temp[0] != 'sign'){
				$return[$temp[0]] = $temp[1];
			}else{
				$return[$temp[0]] = $temp[1]."=";
			}
		}
		
		return $return;
	}
	
	/**
	 * 用户主动签约
	 */
	public function userBindCard(){
		$host = "http://" .$_SERVER['HTTP_HOST'];
		$returnUrl = $host."/Upay/userBindCardReturn.json";
		$param=<<<PARAM
merId={$this->merId}&merCustId={$this->merCustId}&signType={$this->signType}&sign={$this->sign}&retUrl={$returnUrl}
PARAM;
		$postUrl = "https://m.soopay.net/q/html5/protIndex.do?".$param."&sign=".$this->sign;
		header("Location: {$postUrl}");
	}
	
	/**
	 * 用户主动签约返回页面
	 * 拿到支付协议存放到数据库
	 */
	public function userBindCardReturn(){
		if($_REQUEST){
			$error_code 			= $_REQUEST['error_code'];				//交易错误码
			$sign_type 				= $_REQUEST['sign_type'];				//签名方式
			$bank_card_type 		= $_REQUEST['bank_card_type'];			//银行卡类型
			$sign 					= $_REQUEST['sign'];					//签名
			$last_four_cardid 		= $_REQUEST['last_four_cardid'];		//银行卡后四位
			$version 				= $_REQUEST['version'];					//版本号
			$media_type 			= $_REQUEST['media_type'];				//媒介类型
			$usr_busi_agreement_id	= $_REQUEST['usr_busi_agreement_id'];	//用户业务协议号
			$service 				= $_REQUEST['service'];					//接口名称
			$gate_id 				= $_REQUEST['gate_id'];					//支付银行
			$usr_pay_agreement_id	= $_REQUEST['usr_pay_agreement_id'];	//支付协议号
			$mer_id 				= $_REQUEST['mer_id'];					//商户编号
			$mer_cust_id			= $_REQUEST['mer_cust_id'];				//用户在商户端的唯一标识
			
			//插入到数据表中..
			var_dump($_GET);
		}
	}
	
	/**
	 * 
	 * 用户主动解约 (直接跳转到UPAY页面解约)
	 * 
	 * 需要参数: 用户标识(若用户业务标识为空该用户标识下的所有卡片都将被解约). 或者 用户业务标识(解除该用户业务标识所绑定的卡片);
	 */
	public function userUnBindCard($usr_pay_agreement_id = ''){
		
		$service = "unbind_mercust_protocol_shortcut";
		$charset = $this->charset;
		$mer_id = $this->merId;
		$signType = $this->signType;
		$version = $this->version;
		$merCustId = $this->merCustId;
		$map = new HashMap();
		$map->put("service", $service);
		$map->put('charset', $this->charset);
		$map->put('mer_id', $this->merId);
		$map->put('sign_type', $this->signType);
		$map->put('version', $this->version);
		$map->put('mer_cust_id', $this->merCustId);
		$map->put('usr_pay_agreement_id', $usr_pay_agreement_id);
		$reqData = MerToPlat::requestTransactionsByGet($map);
		$url = $reqData->getUrl();
		$ch = curl_init($url) ;
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true) ; // 获取数据返回
		curl_setopt($ch, CURLOPT_BINARYTRANSFER, true) ; // 在启用 CURLOPT_RETURNTRANSFER 时候将获取数据返回
		$access = curl_exec($ch) ;
		curl_close($ch);
		
		preg_match('/CONTENT="(.*?)"/s',$access,$res);
		$tmp = explode("&",$res[1]);
		
		$return = array();
		foreach($tmp as $key=>$value){
			$temp = explode("=",$value);
			if($temp[0] != 'sign'){
				$return[$temp[0]] = $temp[1];
			}else{
				$return[$temp[0]] = $temp[1]."=";
			}
		}
		
		
		if($return['ret_code'] == '0000'){
			return true; //解约成功
		}else{
			return false; //解约失败, 改用户没有关联的卡
		}
	}
	
	/**
	 * 查询用户是否绑定过银行卡
	 * 
	 * 需要参数: 用户标识.
	 * 
	 * 参数: 银行卡类型: 信用卡.CREDITCARD, 储值卡.DEBITCARD
	 */
	public function searchUserBindCard($cardType='CREDITCARD'){
		if($cardType === 'CREDITCARD' || $cardType === 'DEBITCARD'){
			$service = 'query_mercust_bank_shortcut';
			$charset = $this->charset;
			$mer_id = $this->merId;
			$sign_type = $this->signType;
			$version = $this->version;
			$pay_type = $cardType;
			$mer_cust_id = $this->merCustId;
			
			$map =new HashMap();
			$map->put("service", $service);
			$map->put("charset", $charset);
			$map->put("mer_id", $mer_id);
			$map->put("sign_type", $sign_type);
			$map->put("version", $version);
			$map->put("pay_type", $pay_type);
			$map->put("mer_cust_id", $mer_cust_id);
			
			$reqData = MerToPlat::makeRequestDataByGet($map);
			$url = $reqData->getUrl();
			$ch = curl_init($url) ;
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, true) ; // 获取数据返回
			curl_setopt($ch, CURLOPT_BINARYTRANSFER, true) ; // 在启用 CURLOPT_RETURNTRANSFER 时候将获取数据返回
			$access = curl_exec($ch) ;
			curl_close($ch);
			
			preg_match('/CONTENT="(.*?)"/s',$access,$res);
			$tmp = explode("&",$res[1]);
			
			$return = array();
			foreach($tmp as $key=>$value){
				$temp = explode("=",$value);
				if($temp[0] != 'sign'){
					$return[$temp[0]] = $temp[1];
				}else{
					$return[$temp[0]] = $temp[1]."=";
				}
			}
			
			if($return['ret_code']!='0000'){
				return false;
			}else{
				return $return['user_bank_list'];
			}
		}else{
			return false;
		}
	}
	
	/**
	 * 查询订单状态
	 * 
	 * 链接: http://weixin.test/Upay/searchOrder.json?order_id=12312321312
	 * 
	 * 参数: 订单号
	 * 
	 * 返回值 array();
	 *	'amount' 订单金额
  	 *	'amt_type' 货币类型
  	 *	'media_type' 媒介标识
  	 *	'mer_date' 订单日期
  	 *	'mer_id' 商户标识
  	 *	'order_id' 订单编号
  	 *	'pay_date' 支付日期
  	 *	'pay_type' 支付类型
  	 *	'product_id' 产品号
  	 *	'refund_amt' 已退金额
  	 *	'ret_code' 返回码
  	 *	'ret_msg' 返回信息
  	 *	'settle_date' 对账日期
  	 *	'sign_type' 签名类型
  	 *	'trade_no' 联动交易号
  	 *	'trade_state' 订单状态
  	 *	'version' 版本号
  	 *	'sign' 签名
	 */
	
	public function searchOrder($order_id){
		
		$service="query_order";
		$charset=$this->charset;
		$mer_id=$this->merId;
		$sign_type=$this->signType;
		$res_format="HTML";
		$version=$this->version;
		$mer_date= date('Ymd');
		
		$map =new HashMap();
		$map->put("service",$service);
		$map->put("charset",$charset);
		$map->put("mer_id",$mer_id);
		$map->put("sign_type",$sign_type);
		$map->put("order_id",$order_id);
		$map->put("mer_date",$mer_date);
		$map->put("res_format",$res_format);
		$map->put("version",$version);
		
		
		$reqData = MerToPlat::requestTransactionsByGet($map);
		$url = $reqData->getUrl();
		
		$ch = curl_init($url) ;
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 获取数据返回
		curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); // 在启用 CURLOPT_RETURNTRANSFER 时候将获取数据返回
		$access = curl_exec($ch);
		curl_close($ch);
		preg_match('/CONTENT="(.*?)"/s',$access,$res);
		$tmp = explode("&",$res[1]);
			
		$return = array();
		foreach($tmp as $key=>$value){
			$temp = explode("=",$value);
			if($temp[0] != 'sign'){
				$return[$temp[0]] = $temp[1];
			}else{
				$return[$temp[0]] = $temp[1]."=";
			}
		}
			
		if($return['ret_code']!='0000'){
			return false;
		}else{
			var_dump($return);
			return $return;
		}
		
	}
	
	/**
	 * 撤销订单
	 * 
	 */	
	private function orderRevoke($order_id, $mer_date, $amount){
		$service = "mer_cancel";
		$sign_type = $this->signType;
		$charset = $this->charset;
		$sign = $this->sign;
		$mer_id = $this->merId;
		$version = $this->version;
		
		$map =new HashMap();
		$map->put("service",$service);
		$map->put("charset",$charset);
		$map->put("mer_id",$mer_id);
		$map->put("sign_type",$sign_type);
		$map->put("order_id",$order_id);
		$map->put("mer_date",$mer_date);
		$map->put("amount",$amount);
		$map->put("version",$version);
		
		$reqData = MerToPlat::requestTransactionsByGet($map);
		$url = $reqData->getUrl();
		
		$ch = curl_init($url) ;
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 获取数据返回
		curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); // 在启用 CURLOPT_RETURNTRANSFER 时候将获取数据返回
		$access = curl_exec($ch);
		curl_close($ch);
		preg_match('/CONTENT="(.*?)"/s',$access,$res);
		$tmp = explode("&",$res[1]);
		Log::write("退款:".$access);
		$return = array();
		foreach($tmp as $key=>$value){
			$temp = explode("=",$value);
			if($temp[0] != 'sign'){
				$return[$temp[0]] = $temp[1];
			}else{
				$return[$temp[0]] = $temp[1]."=";
			}
		}
		return $return;
	}
	
	/**
	 *
	 * 订单退款
	 *
	 * 链接: http://weixin.test/Upay/orderRefund.json?pay_order_id=12312321312&refund_amount=1&org_amount=1
	 *
	 * 参数:
	 * 	$pay_order_id 订单号
	 *  $refund_amount 退款金额，单位为分
	 *  $org_amount 原订单金额
	 *
	 *  返回值
	 *    'amount' 交易金额
	 *    'mer_date' 商户订单日期
	 *    'mer_id' 商户标识
	 *    'order_id' 订单号
	 *    'refund_no' 退款流水号.
	 *    'refund_state' 退款状态
	 *    'ret_code' 返回码
	 *    'ret_msg' 返回信息
	 *    'sign_type' 签名类型
	 *    'version' 版本号
	 *    'sign' 签名
	 */
	private function orderRefund($pay_order_id, $refundTransactionId, $refund_amount, $org_amount, $order_date) {
		$host = C("SERVER_HOST");
		
		$customerId = Session::$user["customerId"];
		$notify_url = $host."/Upay/refundStatusResponse.json?merPrive=" . $customerId;
		
		$service="mer_refund";
		$charset=$this->charset;
		$sign_type=$this->signType;
		$sign = $this->sign;
		$mer_id=$this->merId;
		$res_format="HTML";
		$version=$this->version;
		$map =new HashMap();
		$map->put("service",$service);
		$map->put("charset",$charset);
		$map->put("notify_url", $notify_url);
		$map->put("mer_id",$mer_id);
		$map->put("sign_type",$sign_type);
		$map->put("sign", $sign);
		$map->put("order_id",$pay_order_id);
		$map->put("mer_date",$order_date);
		$map->put("res_format",$res_format);
		$map->put("version",$version);
		$map->put("refund_no",$refundTransactionId); //退款流水号
		$map->put("refund_amount",$refund_amount); //退款金额
		$map->put("org_amount", $org_amount); // 原订单金额
		
		$reqData = MerToPlat::requestTransactionsByGet($map);
		$url = $reqData->getUrl();
		
		$ch = curl_init($url);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 获取数据返回
		curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); // 在启用 CURLOPT_RETURNTRANSFER 时候将获取数据返回
		$access = curl_exec($ch);
		Log::write($access);
		curl_close($ch);
		preg_match('/CONTENT="(.*?)"/s',$access,$res);
		$tmp = explode("&",$res[1]);
			
		$return = array();
		foreach($tmp as $key=>$value){
			$temp = explode("=",$value);
			if($temp[0] != 'sign'){
				$return[$temp[0]] = $temp[1];
			}else{
				$return[$temp[0]] = $temp[1]."=";
			}
		}
		return $return;
	}
	
	
	public function upayRefund($oid, $pay_order_id, $refundTransactionId, $refundId, $org_amount, $refund_amount, $order_time){
		$order_date = date('Ymd',strtotime($order_time));
		$now_date = date('Ymd');
		if($now_date - $order_date == 0){
			$result = self::orderRevoke($pay_order_id, $order_date, $org_amount);
			if($result['ret_code']=='0000'){
				R('Product/refundStatistics', array($oid,$refund_amount));
				ProductOrder::updateOrderRefund($oid, $refundId, true, $result['ret_msg']);
			}else{
				ProductOrder::updateOrderRefund($oid, $refundId, false, $result['ret_msg']);
			}
		} else {
			$result = self::orderRefund($pay_order_id, $refundTransactionId, $refund_amount, $org_amount, $order_date);
			/*
			if($result['ret_code']=='0000'){
				ProductOrder::updateOrderRefund($oid, $refundId, true, $result['ret_msg']);
			}else{
				ProductOrder::updateOrderRefund($oid, $refundId, false, $result['ret_msg']);
			}
			*/
		}
		
		if($result['ret_code']=='0000'){
			Output::instance()->resultCode(code_product_order_cancel_access,$result['ret_msg']);
		}else{
			Output::instance()->resultCode(code_product_order_cancel_denied,$result['ret_msg']);
		}
	}
	
	/**
	 * 数据对账
	 * 
	 *	平台响应数据格式说明：
	 *	平台响应数据为对账文件，供商户下载。
	 *	文件格式说明：
	 *	文件头是一行记录，每笔交易对应文件中的一行，每个数据域用<逗号>“,”分割；最后一行是汇总信息
	 *	文件头信息（第一行）: TRADEDETAIL-START,商户号（mer_id）,对账日期（settle_date）,版本号（version）,返回码（ret_code）,返回信息（ret_msg） [回车换行]
	 *	每笔交易：商户号（mer_id）,商品号（goods_id）,手机号（mobile_id）,订单号（order_id）,定单日期（mer_date）,支付日期（pay_date）,金额（amount）,付款类型（amt_type）,银行类型（gate_id）,对账日期（settle_date）,交易类型（trans_type）,交易状态（trans_state）,银行对账状态（bank_check）,支付产品编号(product_id) ,退费流水号(refund_no) , 交易成功时间(trans_time) [回车换行]
	 *	文件汇总信息（最后一行）：TRADEDETAIL-END,商户号（mer_id）,交易日期（settle_date）,总笔数,总金额
	 */
	public function dowloadSettleFile(){
		
		$service="download_settle_file";
		$sign_type=$this->signType;
		$sign = $this->sign;
		$mer_id=$this->merId;
		$version=$this->version;
		$settle_date = date('Ymd'); //对账日期
		$map =new HashMap();
		$map->put("service",$service);
		$map->put("mer_id",$mer_id);
		$map->put("sign_type",$sign_type);
		$map->put("sign", $sign);
		$map->put("version",$version);
		$map->put("settle_date",$settle_date);
		
		$reqData = MerToPlat::requestTransactionsByGet($map);
		$url = $reqData->getUrl();
		header("Location: {$url}");
	}
	
	/**
	 * 退款状态变更通知
	 * 
	 */
	public function refundStatusResponse(){
		$oid = $_REQUEST['order_id'];
		$refundTransactionId =  $_REQUEST['refund_no'];
		
		$data = new HashMap();
		$data->put("mer_date", $_REQUEST['mer_date']);
		if($_REQUEST['error_code']!=null)
			$data->put("error_code", $_REQUEST['error_code']);
		$data->put("mer_id", $_REQUEST['mer_id']);
		$data->put("order_id", $oid);
		$data->put("refund_amt", $_REQUEST['refund_amt']);
		$data->put("refund_no", $refundTransactionId);
		$data->put("refund_state", $_REQUEST['refund_state']);
		$data->put("version", $_REQUEST['version']);
		$data->put("sign", $_REQUEST['sign']);
		$data->put("sign_type", $_REQUEST['sign_type']);
		
		//获取请求数据
		$error_code = $data->get("error_code");
		$mer_date = $data->get("mer_date");
		$mer_id = $data->get("mer_id");
		$order_id = $data->get("order_id");
		$refund_amt = $data->get("refund_amt");
		$refund_no = $data->get("refund_no");
		$version = $data->get("version");
		$sign = $data->get("sign");
		$sign_type = $data->get("sign_type");
		
		// 如果状态不为退费成功,则不处理
		$refund_state = $data->get("refund_state");
		Log::write('refund state :' . $refund_state);
		
		
		//获取UMPAY平台请求商户的退款结果通知数据,并对请求数据进行验签,此时商户接收到的退款结果通知会存放在这里,商户可以根据此处的trade_state订单状态来更新订单
		$resData = new HashMap();
		try{
			//获取UMPAY平台请求商户的退款结果通知数据,并对请求数据进行验签
			//如验证平台签名正确，即应响应UMPAY平台返回码为0000。【响应返回码代表通知是否成功，和通知的退款结果】
			//验签支付结果通知 如验签成功，则返回ret_code=0000
			$reqData = PlatToMer::getNotifyRequestData($data);
		
			$resData->put("ret_code","0000");
		} catch (Exception $e){
			//如果验签失败，则抛出异常，返回ret_code=1111
			System.out.printf("验证签名发生异常" + $e);
		
			$resData->put("ret_code","1111");
		}
		//验签后的数据都组织在resData中。
		//生成平台响应UMPAY平台数据,将该串放入META标签，以下几个参数为结果通知必备参数
		
		
		//生成平台响应UMPAY平台数据,将该串放入META标签
		$resData->put("mer_id", $data->get("mer_id"));
		$resData->put("sign_type", $data->get("sign_type"));
		$resData->put("version", $data->get("version"));
		$resData->put("ret_msg", "success");
		$data = MerToPlat::RefundnotifyResponseData($resData);
		
		
		$customerId = $_REQUEST['merPrive'];
		Log::write('refund merPrive:' . $customerId);
		Session::switchCustomer($customerId);
		
		$RefundModel = M("module_product_order_refund");
		$whereRefund["refundTransactionId"] = $refundTransactionId;
		$refund = $RefundModel->where($whereRefund)->field('id, oid')->find();
		if (!$refund) {
			Log::write('Upay refund order Not found ' . $RefundModel->getLastSql());
			return;
		}
		
		//验签正确
		if($resData->get('ret_code') == '0000' && $refund_state == REFUND_SUCCESS){
			ProductOrder::updateOrderRefund($refund["oid"], $refund["id"], true, $resData->get('ret_msg'));
			
			$returnStr = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"
			. "<HTML><TITLE></TITLE><HEAD></HEAD>"
			. "<META NAME=\"MobilePayPlatform\"  CONTENT=\"{$data}\" />"
			. "<BODY></BODY></HTML>";
			echo $returnStr;
		}else if ($refund_state  == REFUND_FAIL) {
			ProductOrder::updateOrderRefund($refund["oid"], $refund["id"], false, $resData->get('ret_msg'));
		}
	}

}